/*
 * Copyright (C) 2010 M. Hautle.
 * 
 * This file is part of SimpleEL.
 * 
 * SimpleEL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * SimpleEL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with SimpleEL. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.simpleel.internal.asm;

import java.util.*;
import ch.msoftch.asm.*;

/**
 * Enumeration of primitive types holding some usefull ASM information for them.
 * 
 * @author M. Hautle
 */
enum PrimitiveType {
    /** {@link Byte}. */
    BYTE(byte.class, Byte.class, "byteValue"),
    /** {@link Boolean}. */
    BOOLEAN(boolean.class, Boolean.class, "booleanValue"),
    /** {@link Character}. */
    CHAR(char.class, Character.class, "charValue"),
    /** {@link Short}. */
    SHORT(short.class, Short.class, "shortValue"),
    /** {@link Integer}. */
    INT(int.class, Integer.class, "intValue"),
    /** {@link Long}. */
    LONG(long.class, Long.class, "longValue"),
    /** {@link Float}. */
    FLOAT(float.class, Float.class, "floatValue"),
    /** {@link Double}. */
    DOUBLE(double.class, Double.class, "doubleValue");

    /** Mapping between the primitive type and the corresponding {@link PrimitiveType}. */
    private static final Map<Class<?>, PrimitiveType> MAPPING = new HashMap<Class<?>, PrimitiveType>();

    /** The name of the wrap method. */
    public static final String WRAP_METHOD = "valueOf";

    /** The represented primitive type */
    private final Class<?> primitive;

    /** Internal name of the wrapper class. */
    public final String wrapper;

    /** Name of the unwrap method. */
    public final String unwrapMethod;

    /** Mehod descriptor of the valueOf method. */
    public final String wrapDescr;

    /** Method descriptor fot the {@link #unwrapMethod}. */
    public final String unwrapDescr;

    static {
        for (PrimitiveType p : values())
            MAPPING.put(p.primitive, p);
    }

    /**
     * @param primitive The primitive type
     * @param wrapper The wrapper type
     * @param unwrapMethod The name of the unwrap method
     */
    private PrimitiveType(Class<?> primitive, Class<?> wrapper, String unwrapMethod) {
        final String pDescr = Type.getType(primitive).getDescriptor();
        this.primitive = primitive;
        this.wrapper = Type.getInternalName(wrapper);
        this.wrapDescr = "(" + pDescr + ")L" + this.wrapper + ";";
        this.unwrapMethod = unwrapMethod;
        this.unwrapDescr = "()" + pDescr;
    }

    /**
     * Resolves the {@link PrimitiveType} for the passed primitive type.
     * 
     * @param type The primitive type
     * @return The corresponding constant
     * @throws IllegalArgumentException If the passed type is not a primitive type
     */
    public static PrimitiveType get(Class<?> type) {
        final PrimitiveType res = MAPPING.get(type);
        if (res == null)
            throw new IllegalArgumentException(type.getName() + " is not a primitive type!");
        return res;
    }
}
